/*
 * price_simulator.hpp
 *
 *  Created on: Apr 2, 2009
 *      Author: Lev
 */

#ifndef PRICE_SIMULATOR_HPP_
#define PRICE_SIMULATOR_HPP_

#include <exception>
#include <vector>
#include <stdexcept>
#include "price_model.hpp"

class invalid_state : public std::exception {
private:
	const char *_message;
public:
	invalid_state( const char *message ) : _message(message) {}
	const char* what() { return _message; }
	~invalid_state() throw() {}
};

enum ResultType {
	ORDERED_ENDPOINTS, // result set contains ordered end price values
	AVERAGED_SEQUENCE // result set contains time sequence of average price values
};

struct SPExperiment {
	SPModelProps spModelProps;
	unsigned nRuns;
	unsigned nPoints;
	double dt;
	ResultType rType;
	SPExperiment& setSPModelProps( const SPModelProps& sProps );
	SPExperiment& setNumberOfRuns( unsigned runs ) { nRuns = runs; return *this; }
	SPExperiment& setNumberOfPoints( unsigned points ) { nPoints = points; return *this; }
	SPExperiment& setTimeInterval( double interval ) { dt = interval; return *this; }
	SPExperiment& setResultType( ResultType type ) { rType = type; return *this; }
};

class StockPriceSimulator {
private:
	StockPriceModel _spModel;
	std::vector<double> _spResults;
	bool _finished;
	void produceAveragedSequence( const SPExperiment& experiment );
	void produceOrderedEndpoints( const SPExperiment& experiment );
public:
	StockPriceSimulator() : _finished(false) {}
	// runs simulation experiment
	void runExperiment( const SPExperiment& experiment ) throw(std::invalid_argument);
	// returns simulation results according to specified result type
	const std::vector<double>& getResults() const { return _spResults; }
};

class SampleEstimations {
private:
	typedef std::vector<double>::const_iterator SPIter;
	std::vector<double> _spResults;
	double _mean;
	double _variance;
public:
	// copies results, calculates sample mean and variance
	SampleEstimations( const std::vector<double> &spResults );
	// returns the sample mean
	double getMean() const { return _mean; }
	// returns the sample variance
	double getVariance() const { return _variance; }
	// TODO: returns the value, below which a given percent of results fall
	double getPercentile( unsigned percent ) const throw(std::invalid_argument);
};

#endif /* PRICE_SIMULATOR_HPP_ */
